package core;

/**
 * A class that models a Memory Bank of shorts
 * @author Ximo Tur ximotur at gmail dot com
 */

public class MemoryClass {
	private short memoryArray[] = null;
	private int maxMem = 0;
	private core.interfaces.MemoryCallbackInterface callback = null;

	/**
	 * Constructor that creates a memory bank with 64k shorts.
	 */
	public MemoryClass(){
		this.maxMem = 65536;
		this.memoryArray = new short[this.maxMem];
	}

	/**
	 * Constructor that creates a memory bank with N shorts.
	 * @param n The amount of words of short that will be contained
	 */
	public MemoryClass(int n){
		this.maxMem = n;
		this.memoryArray = new short[this.maxMem];
	}

	/**
	 * Constructor that creates a memory bank with N shorts and assigns the callback
	 * interface (to inform about changes)
	 * @param n The amount of words of short that will be contained.
	 * @param callback The interface to inform about memory changes.
	 */
	public MemoryClass(int n, core.interfaces.MemoryCallbackInterface callback){
		this.maxMem = n;
		this.memoryArray = new short[this.maxMem];
		this.callback = callback;
	}

	/**
	 * Sets the callback object for the Register Class
	 * @param cObject The object that will act as callback object.
	 */
	public void setCallBack(core.interfaces.MemoryCallbackInterface cObject){
		this.callback = cObject;
	}

	/**
	 * Sets the address with the given word (short) value
	 * 
	 * @param address is the address to be set
	 * @param value is the value 
	 */
	synchronized public void setWord(int address, short value){
		//Deal with casting java problem, that does NOT have unsigned shorts
		address = (address & 0x0000FFFF);
		if((address >= 0) && (address<this.maxMem)){
			this.memoryArray[address] = value;
			if(this.callback != null){
				this.callback.memoryChanged(address);
			}
		}else{
		}
	}
	/**
	 * Silently Sets the address with the given word (short) value
	 * 
	 * @param address is the address to be set
	 * @param value is the value 
	 */
	synchronized public void ssetWord(int address, short value){
		//Deal with casting java problem, that does NOT have unsigned shorts
		address = (address & 0x0000FFFF);
		if((address >= 0) && (address<this.maxMem)){
			this.memoryArray[address] = value;
		}else{
		}
	}

	/**
	 * Returns the word from the memory bank addressed by address  
	 * @param address the memory address to be returned
	 * @return The value of the word
	 */
	synchronized public short getWord(int address){
		//Deal with casting java problem, that does NOT have unsigned shorts
		address = (address & 0x0000FFFF);
		if((address >= 0) && (address<this.maxMem)){
			if(this.callback != null){
				this.callback.memoryAccessed(address);
			}
			return this.memoryArray[address];
		}else{
			return (short)0;
		}
	}
	/**
	 * Returns the number of Memory Words on the bank
	 * @return the number of Memory Words on the bank
	 */
	public int getMax(){
		return(this.maxMem);
	}

	//Extremely dirty trick for java: encode two shorts into a Integer
	public java.util.Vector<java.lang.Integer> getMemoryVector(int offset, int n){
		java.util.Vector<java.lang.Integer> v = new java.util.Vector<java.lang.Integer>();
		for(int i=offset; (i<(offset + n))&&(i<this.maxMem); i++){
			v.add(java.lang.Integer.valueOf((i<<16)|(0x0000FFFF & this.memoryArray[i])));
		}
		return(v);
	}
	public java.util.Vector<java.lang.Integer> getMemoryVector(){
		return(this.getMemoryVector((short)0, (short)30));
	}
}
